//////////////////////////////////////////////////////////////////////////
///	\file:	MObj.cpp
///	Copyright (MingYou) 2009 - All Rights Reserved
///	Author:	Robert.Ma
///	Date:	[2009/04/28]
///	Description:
///		
//////////////////////////////////////////////////////////////////////////
#include "StdAfx.h"
#include "MObj.h"
#include "MThread.h"

#ifdef _DEBUG
#include "CETool.h"
#include <set>
#include <string>


class CObjCounter
{
	typedef std::set<const CMObj*> CObjSet;

public:
	CObjCounter()
	{
		m_hMutex = ::CreateMutex(NULL, FALSE, L"ObjectMutex");
	}

	~CObjCounter()
	{
		size_t nCounts = m_Set.size();

		if ( nCounts > 0 )
		{
			MTRACE(L"Memory leak: %d\n", nCounts);
			ASSERT(FALSE);

			CObjSet::iterator	iter = m_Set.begin();
			CMObj*				pObj = NULL;
			std::string			strObj;

			for ( ; iter != m_Set.end(); ++iter )
			{
				pObj	= const_cast<CMObj*>(*iter);
				strObj	= typeid(*pObj).name();

				//delete pObj;
			}
		}

		::CloseHandle(m_hMutex);
	}

	DWORD Increase(const CMObj* pObj)
	{
		CMMutex lock(m_hMutex);

		if ( !lock.Lock(200) )
		{
			return ULONG_MAX;
		}

		CObjSet::iterator iter = m_Set.find(pObj);

		if ( m_Set.end() == iter )
		{
			m_Set.insert(pObj);
		}
		else
		{
			ASSERT(FALSE);
		}

		return m_Set.size();
	}

	DWORD Decrease(const CMObj* pObj)
	{
		CMMutex lock(m_hMutex);

		if ( !lock.Lock(200) )
		{
			return ULONG_MAX;
		}

		CObjSet::iterator iter = m_Set.find(pObj);

		if ( m_Set.end() != iter )
		{
			m_Set.erase(iter);
		}
		else
		{
			ASSERT(FALSE);
		}

		return m_Set.size();
	}

private:
	CObjSet	m_Set;
	HANDLE	m_hMutex;
};

CObjCounter objCounter;

#define INCREASE_COUNTER objCounter.Increase(this);
#define DECREASE_COUNTER objCounter.Decrease(this);

#else

#define INCREASE_COUNTER __noop
#define DECREASE_COUNTER __noop

#endif

CMObj::CMObj(void)
{
	INCREASE_COUNTER
}

CMObj::~CMObj(void)
{
	DECREASE_COUNTER
}
